package com.liveinstars.im.core.service.impl;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.liveinstars.api.dto.ImGetUserInfo;
import com.liveinstars.api.facade.IActivityApi;
import com.liveinstars.api.facade.ImUserCentreApi;
import com.liveinstars.im.common.enums.IMExceptionEnum;
import com.liveinstars.im.common.enums.NoticeMessageTypeEnum;
import com.liveinstars.im.common.enums.PassThroughMessageTypeEnum;
import com.liveinstars.im.domain.dao.model.ChatGroup;
import com.liveinstars.im.domain.dao.model.ChatGroupMember;
import com.liveinstars.im.domain.dao.model.Todo;
import com.liveinstars.im.domain.manager.ChatGroupManager;
import com.liveinstars.im.domain.manager.ChatGroupMemberManager;
import com.liveinstars.im.domain.manager.TodoManager;
import com.liveinstars.im.entity.ChatMessage;
import com.liveinstars.im.entity.Msg;
import com.liveinstars.api.im.query.TodoQuery;
import com.liveinstars.im.api.MsgGeneratorService;
import com.liveinstars.im.common.enums.ChatGroupTypeEnum;
import com.liveinstars.im.common.exception.IMRuntimeException;
import com.liveinstars.im.core.service.FriendsService;
import com.liveinstars.im.core.service.MessageService;
import com.liveinstars.im.core.service.TodoService;
import com.liveinstars.im.corebean.MsgHelper;
import com.liveinstars.im.util.StringUtils;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * @author: zhouze
 * @date: 2020/4/30
 */
@Service("todoService")
public class TodoServiceImpl implements TodoService {

    private final static Logger logger = LoggerFactory.getLogger(TodoServiceImpl.class);

    @Autowired
    private TodoManager todoManager;

    @Autowired
    private FriendsService friendsService;

    @Autowired
    private ImUserCentreApi imUserCentreApi;

    @Autowired
    private MessageService messageService;

    @Autowired
    private ChatGroupMemberManager chatGroupMemberManager;

    @Autowired
    private ChatGroupManager chatGroupManager;

    @Autowired
    private MsgGeneratorService msgGeneratorService;

    @Autowired
    private IActivityApi activityApi;

    @Override
    public void add(Todo todo) {
        todoManager.save(todo);
    }

    @Override
    public void updateById(Todo todo) {
        todoManager.updateById(todo);
    }

    @Override
    public Todo getById(Long id) {
        Todo todo = todoManager.getById(id);
        return todo;
    }

    @Override
    public void finishTodo(Long id, String handleMsg, Boolean agree) {
        Todo todo = new Todo();
        todo.setId(id);
        todo.setComplete(true);
        todo.setHandleDate(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().getEpochSecond());
        todo.setHandleMsg(handleMsg);
        todo.setAgree(agree);
        todoManager.updateById(todo);
    }

    @Override
    public List<Todo> listUnCompleteTodoByUserIdAndStartId(Long userId, Long startId) {
        TodoQuery todoQuery = new TodoQuery();
        todoQuery.setComplete(false);
        todoQuery.setToId(userId);
        todoQuery.setStartId(startId);
        List<Todo> todoList = todoManager.listByQuery(todoQuery);
        return todoList;
    }

    @Override
    public Todo getLastTodoByActivityId(Long fromId, Long toId, Integer type, Integer activityId) {
        TodoQuery todoQuery = new TodoQuery();
        todoQuery.setToId(toId);
        todoQuery.setFromId(fromId);
        todoQuery.setComplete(false);
        todoQuery.setType(type);
        todoQuery.setActivityId(activityId);
        List<Todo> list = todoManager.listByQuery(todoQuery);
        if (CollectionUtils.isNotEmpty(list)) {
            return list.get(0);
        }
        return null;
    }
    @Override
    public Todo getLastTodoByGroupId(Long fromId, Long toId, Integer type, Long groupId) {
        TodoQuery todoQuery = new TodoQuery();
        todoQuery.setToId(toId);
        todoQuery.setFromId(fromId);
        todoQuery.setComplete(false);
        todoQuery.setType(type);
        todoQuery.setChatGroupId(groupId);
        List<Todo> list = todoManager.listByQuery(todoQuery);
        if (CollectionUtils.isNotEmpty(list)) {
            return list.get(0);
        }
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Todo dealWithTodo(Long userId, Long todoId, Boolean agreeOrNot, String handleMsg) {
        Boolean isSuccess;
        Todo todo = this.getById(todoId);
        if (todo == null) {
            throw new IMRuntimeException(IMExceptionEnum.TODO_DEAL_IS_NOT_EXIST);
        }

        if(!todo.getUserId().equals(userId)){
            throw new IMRuntimeException(IMExceptionEnum.CHAT_GROUP_OPERATION_PERMISSION_DENIED);
        }

        if (todo.getComplete()) {
            throw new IMRuntimeException(IMExceptionEnum.TODO_DEAL_WITH_IS_REPEAT);
        }
        String dealMsg = "已拒绝";
        todo.setAgree(false);
        todo.setComplete(true);
        if (agreeOrNot) {
            switch (todo.getType()) {
                case Todo.TODO_TYPE_ADD_FRIENDS:
                    agreeFriendsTodo(todo);
                    dealMsg = "成功添加成好友。";
                    break;
                case Todo.TODO_TYPE_JOIN_GROUP:
                    ChatGroup chatGroup = chatGroupManager.getById(todo.getGroupId());
                    if(chatGroup == null){
                        throw new IMRuntimeException(IMExceptionEnum.CHAT_GROUP_IS_NOT_EXIST);
                    }
                    int count = chatGroupMemberManager.countByChatGroupId(todo.getGroupId());
                    if (count > 200) {
                        throw new IMRuntimeException(IMExceptionEnum.CHAT_GROUP_JOIN_LIMIT);
                    }
                    //不同的招募活动加入同一个群的情况，会重复发通知，如果已经在群里面不重复加入
                    ChatGroupMember chatGroupMemberByGroupIdAndUserId = chatGroupMemberManager.getChatGroupMemberByGroupIdAndUserId(todo.getGroupId(), todo.getUserId());
                    if(chatGroupMemberByGroupIdAndUserId == null) {
                        agreeJoinChatGroupTodo(todo);
                    }
                    isSuccess = activityApi.addActivityMember(Math.toIntExact(todo.getFromId()), Math.toIntExact(todo.getUserId()), todo.getActivityId());
                    if(!isSuccess){
                        throw new IMRuntimeException(IMExceptionEnum.TODO_DEAL_TYPE_ERROR);
                    }
                    dealMsg = !StringUtils.isEmpty(handleMsg) ? handleMsg : "已添加为群成员。";
                    break;
                case Todo.TODO_TYPE_ADD_INTEREST:
                    isSuccess = activityApi.addActivityMember(Math.toIntExact(todo.getFromId()), Math.toIntExact(todo.getUserId()), todo.getActivityId());
                    if(!isSuccess){
                        throw new IMRuntimeException(IMExceptionEnum.TODO_DEAL_TYPE_ERROR);
                    }
                    dealMsg = handleMsg;
                    break;
                default:
                    throw new IMRuntimeException(IMExceptionEnum.TODO_DEAL_TYPE_ERROR);
            }
        }
        finishTodo(todoId, dealMsg, agreeOrNot);
        return todo;
    }

    @Override
    public Todo getTodoByActivityIdAndUserId(Long userId, Integer id) {
        TodoQuery todoQuery = new TodoQuery();
        todoQuery.setFromId(userId);
        todoQuery.setComplete(false);
        todoQuery.setActivityId(id);
        List<Todo> list = todoManager.listByQuery(todoQuery);
        if (CollectionUtils.isNotEmpty(list)) {
            return list.get(0);
        }
        return null;
    }

    @Override
    public List<Todo> listUnCompleteActivityTodoByUserId(Long userId) {
        List<Todo> todoList = todoManager.listUnCompleteActivityTodoByUserId(userId);
        return todoList;
    }

    public void agreeFriendsTodo(Todo todo) {
        todo.getFromId();
        friendsService.makeFriends(todo.getFromId(),todo.getUserId(), 1);
        ImGetUserInfo userInfo = imUserCentreApi.imGetUserInfo(todo.getUserId());
        ChatMessage chatMessage = new ChatMessage(todo.getUserId(), todo.getFromId(), UUID.randomUUID().toString(),
                ChatMessage.STATUS_SEND, ChatMessage.MSG_TYPE_UU, userInfo.getUserName() + "加您为好友！",
                true, (int) LocalDateTime.now().atZone(ZoneId.systemDefault()).toEpochSecond(),
                2, 0L);
        chatMessage.setType(ChatMessage.TYPE_SEND);
        chatMessage.setId(messageService.getMsgId());
        try {
            messageService.sendMessage(chatMessage);
            Map<String, Long> data = Maps.newHashMap();
            data.put("user_id", todo.getUserId());
            Msg.Message noticeMessage = MsgHelper.newNoticeMessage(NoticeMessageTypeEnum.ADD_FRIEND.getValue(), 0, JSON.toJSONString(data));
            msgGeneratorService.sendRoamingMessage(todo.getFromId(), PassThroughMessageTypeEnum.USER, noticeMessage);
        } catch (Exception e) {
            logger.error("agreeFriendsTodo error: {}", e.getMessage(), e);
        }
    }

    public void agreeJoinChatGroupTodo(Todo todo) {
        ImGetUserInfo userInfo = imUserCentreApi.imGetUserInfo(todo.getFromId());
        List<ChatGroupMember> list = Lists.newArrayList();
        ChatGroupMember chatGroupMember = new ChatGroupMember();
        chatGroupMember.setUserId(todo.getFromId());
        chatGroupMember.setChatGroupId(todo.getGroupId());
        chatGroupMember.setGroupType(ChatGroupTypeEnum.CHAT_CIRCLE.getValue());
        list.add(chatGroupMember);
        chatGroupMemberManager.batchSaveMember(list, todo.getGroupId());
        ChatMessage chatMessage = new ChatMessage(todo.getUserId(), 0L, UUID.randomUUID().toString(),
                ChatMessage.STATUS_SEND, ChatMessage.MSG_TYPE_UCG, userInfo.getUserName() + "加入圈子！",
                true, (int) LocalDateTime.now().atZone(ZoneId.systemDefault()).toEpochSecond(),
                2, todo.getGroupId());
        chatMessage.setType(ChatMessage.TYPE_SEND);
        chatMessage.setId(messageService.getMsgId());
        try {
            messageService.sendMessage(chatMessage);
            // 推送添加群组通知
            Map<String, Long> joinGroupData = Maps.newHashMap();
            joinGroupData.put("group_id", todo.getGroupId());
            Msg.Message noticeMessage2 = MsgHelper.newNoticeMessage(NoticeMessageTypeEnum.JOIN_CHAT_GROUP.getValue(), 0, JSON.toJSONString(joinGroupData));
            msgGeneratorService.sendRoamingMessage(todo.getFromId(), PassThroughMessageTypeEnum.USER, noticeMessage2);
        } catch (Exception e) {
            logger.error("agreeJoinChatGroupTodo error: {}", e.getMessage(), e);
        }
    }
}
